package com.salim.leetcode.$36;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class ValidSudoku {
    public boolean isValidSudoku(char[][] board) {
        boolean[] check = new boolean[9];
        if(horizontal(board,check)){
            if(vertical(board,check)){
                if(ninenine(board,check)){
                    return true;
                }
            }
        }
        return false;
    }

    private boolean horizontal(char[][] board,boolean[] check){
        for (int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[i][j]=='.'){
                    continue;
                }else if(islegal(board[i][j])){
                    if(!check(check,board[i][j])){
                        return false;
                    }
                }else{
                    return false;
                }
            }
            flush(check);
        }
        return true;
    }

    private boolean vertical(char[][] board,boolean[] check){
        for (int i=0;i<9;i++){
            for(int j=0;j<9;j++){
                if(board[j][i]=='.'){
                    continue;
                }else if(islegal(board[j][i])){
                    if(!check(check,board[j][i])){
                        return false;
                    }
                }else{
                    return false;
                }
            }
            flush(check);
        }
        return true;
    }

    private boolean ninenine(char[][] board,boolean[] check){
        int[][] offset = {
            {0,0},{0,3},{0,6},{3,0},{3,3},{3,6},{6,0},{6,3},{6,6}
        };
        for(int a=0;a<9;a++){
            for(int i=0;i<3;i++){
                for(int j=0;j<3;j++){
                    if(board[i+offset[a][0]][j+offset[a][1]]=='.'){
                        continue;
                    }else if(islegal(board[i+offset[a][0]][j+offset[a][1]])){
                        if(!check(check,board[i+offset[a][0]][j+offset[a][1]])){
                            return false;
                        }
                    }else{
                        return false;
                    }
                }
            }
            flush(check);
        }
        return true;
    }

    private void flush(boolean[] check){
        for(int i=0;i<9;i++){
            check[i] = false;
        }
    }

    private boolean islegal(char num){
        if(num>=49 && num<=57){
            return true;
        }else{
            return false;
        }
    }

    private boolean check(boolean[] check,char num){
        if(check[num-49]){
            return false;
        }else{
            check[num-49] = true;
            return true;
        }
    }

}
